home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-08-18 | 36.4 KB | 1,122 lines |
- (* :Title: Discrete-Time Fourier Transforms *)
-
- (* :Authors: Wally McClure, Brian Evans, James McClellan *)
-
- (*
- :Summary: This file will compute the forward and inverse
- discrete-time Fourier Transform of a signal.
- *)
-
- (* :Context: SignalProcessing`Digital`DTFT` *)
-
- (* :PackageVersion: 2.7 *)
-
- (*
- :Copyright: Copyright 1989-1991 by Brian L. Evans
- Georgia Tech Research Corporation
-
- Permission to use, copy, modify, and distribute this software
- and its documentation for any purpose and without fee is
- hereby granted, provided that the above copyright notice
- appear in all copies and that both that copyright notice and
- this permission notice appear in supporting documentation,
- and that the name of the Georgia Tech Research Corporation,
- Georgia Tech, or Georgia Institute of Technology not be used
- in advertising or publicity pertaining to distribution of the
- software without specific, written prior permission. Georgia
- Tech makes no representations about the suitability of this
- software for any purpose. It is provided "as is" without
- express or implied warranty.
- *)
-
- (*
- :History: start October 2, 1989
- made into package April 18, 1990
- made into release May 25, 1990
- debugged fully September 6, 1990
- *)
-
- (* :Keywords: discrete-time Fourier transform *)
-
- (*
- :Source: {Discrete-Time Signal Processing} by A. V. Oppenheim and
- Ronald W. Schafer. Prentice Hall. 1989
- *)
-
- (*
- :Warning: If the input does not match any given transform, a nasty
- expression is returned. (But isn't this true for any
- invalid transform in the signal processing packages?)
- *)
-
- (* :Mathematica Version: 1.2 or 2.0 *)
-
- (* :Limitation: *)
-
- (*
- :Discussion: This file implements the forward and inverse DTFT.
- The DTFTransform rule base (DTFTRules) consists of 5
- property rules, 2 structure rules (upsampling and
- downsampling), 13 lookup rules (for those functions
- which have a DTFT but not a z-transform), and 5
- strategies -- distribute polynomials, expand terms
- in cosine, sine, and exponential functions, and a
- call to the forward z-transform rule base (if all
- else fails). The only functions supporting the for-
- ward DTFT which depend on the implementation of the
- z-transform are ZtoDTFT and DTFTtoZ.
-
- The InvDTFTransform is similarly arranged, having 11
- lookup rules, 6 property rules, and 6 strategies
- (including a call to the inverse z-transform rule
- base). Only one rule in InvDTFTRules is dependent
- on the implementation of the inverse z-transform
- rule base InvZTransform.
-
- MyDTFT[f, n, w] determines the discrete-time Fourier transform
- of f with respect to n, where w is the frequency variable.
-
- MyInvDTFT[f, w, n] determines the inverse discrete-time Fourier
- transform of f with respect to w, where n is a "time" variable.
-
- These transform pairs are valid with respect to the DTFT formulas:
-
- n
- (-1) w
- ----- <-----> - ------ CPulse[2 Pi, w + Pi]
- n 2 I Pi
-
- n
- (-1)
- - 2 I Pi ----- <-----> w CPulse[2 Pi, w + Pi]
- n
- *)
-
- (*
- :Functions: DTFTransform
- InvDTFTransform
- *)
-
-
-
- (* B E G I N P A C K A G E *)
-
- BeginPackage[ "SignalProcessing`Digital`DTFT`",
- "SignalProcessing`Digital`DSupport`",
- "SignalProcessing`Digital`InvZTransform`",
- "SignalProcessing`Digital`ZTransform`",
- "SignalProcessing`Digital`ZSupport`",
- "SignalProcessing`Support`TransSupport`",
- "SignalProcessing`Support`ROC`",
- "SignalProcessing`Support`SigProc`",
- "SignalProcessing`Support`SupCode`" ]
-
-
- If [ TrueQ[ $VersionNumber >= 2.0 ],
- Off[ General::spell ];
- Off[ General::spell1 ] ];
-
-
- (* U S A G E I N F O R M A T I O N *)
-
- DTFTData::usage =
- "DTFTData is a data-tag."
-
- DTFTransform::usage =
- "DTFTransform[function, in variable(s), out variable(s), options] \
- returns the discrete-time Fourier transform of the input function. \
- Note that this transform may rely on the z-transform and the \
- substitution z = Exp[I w], which is not valid if the region of \
- convergence does not include the unit circle. Also note that \
- only the first two arguments are required."
-
- InvDTFTransform::usage =
- "InvDTFTransform[function, in variable(s), out variable(s), options] \
- return the inverse discrete-time Fourier transform (inverse DTFT) \
- of the input function. \
- The first two arguments are required. \
- By default, the inverse DTFT rule base will apply the definition \
- of the inverse DTFT when all other attempts to find the inverse \
- have failed."
-
- (* E N D U S A G E I N F O R M A T I O N *)
-
-
- Begin[ "`Private`" ]
-
-
- (* B E G I N P A C K A G E *)
-
- (* Global variables *)
- nList = {}
- wList = {}
- zList = {}
- multidFlag = False
-
- (* displayFixUp *)
- displayFixUp[ fixUp_, op_ ] :=
- Append[ fixUp[op], TransformLookup -> Replace[TransformLookup, op] ]
-
- (* validvarQ-- Valid variable checker *)
- validvarQ[ x_Symbol ] := True
- validvarQ[ x_List ] := Apply[And, Map[VariableQ, x]]
- validvarQ[ x_ ] := False
-
- (* Generate a unique symbol with a Global context. *)
- unique[x_] :=
- Block [ {context, newsymbol},
- context = $Context;
- $Context = "Global`";
- newsymbol = Unique[x];
- $Context = context;
- newsymbol ]
-
-
- (* B E G I N F O R W A R D D T F T *)
-
- (* Conversion from operator notation to function notation *)
- Unprotect[DTFT]
- DTFT/: TheFunction [ DTFT[n_, w_][f_] ] := DTFTransform[f, n, w]
- Protect[DTFT]
-
- (* Options for the DTFT *)
- DTFTransform/: Options[ DTFTransform ] :=
- displayFixUp[ fixUp, { Dialogue -> False } ~Join~ Options[ZTransform] ]
-
- (* Extension of TheFunction operator. *)
- DTFTData/: TheFunction [ DTFTData[ trans_, var_ ] ] := trans
-
- (* Magnitude/Phase plot of a DTFT object *)
- mppoptions = { Domain -> Continuous, DomainScale -> Linear,
- MagRangeScale -> Linear, PhaseRangeScale -> Degree,
- PlotRange -> All }
-
- DTFTData/: MagPhasePlot[DTFTData[trans_, FVariables[w_Symbol]]] :=
- MagPhasePlot[ trans, {w, -Pi, Pi}, mppoptions ]
-
- DTFTData/: MagPhasePlot[DTFTData[trans_, FVariables[{w1_Symbol, w2_Symbol}]]] :=
- MagPhasePlot[ trans, {w1, -Pi, Pi}, {w2, -Pi, Pi}, mppoptions ]
-
- (* Input a function and test to see if needs to be sent to *)
- (* the multidimensional or one-dimensional Fourier transform. *)
- DTFTransform[ f_ ] :=
- Message[ Transform::novariables, "n (time)", GetVariables[f] ]
-
- DTFTransform[ f_, n_ ] :=
- DTFTransform [ f, n, DummyVariables[Length[n], Global`w] ]
-
- DTFTransform[ f_, n_, w_, options___ ] :=
- Message[ Transform::badvar, "discrete-time", DTFTransform, n ] /;
- ! validvarQ[n]
-
- DTFTransform[ f_, n_, w_, options___ ] :=
- Message[ Transform::badvar, "continuous-frequency", DTFTransform, w ] /;
- ! validvarQ[w]
-
- DTFTransform[ f1_, n_, w_, options___ ] :=
- Block [ {op, trans, vars, zvars},
- vars = If [ Length[n] != Length[w],
- DummyVariables[Length[n], Global`w],
- w ];
- zvars = DummyVariables[Length[n], z];
-
- nList = ToList[n];
- wList = ToList[vars];
- zList = ToList[zvars];
-
- op = ToList[options] ~Join~ Options[DTFTransform];
- multidFlag = ( Length[n] > 1 );
- trans = If [ multidFlag,
- multiDDTFT[f1, n, vars, zvars, op],
- MyDTFT[f1, n, vars, zvars, op] ];
-
- If [ InformUserQ[op],
- Scan[explain, trans, Infinity] ];
-
- DTFTData[ trans, FVariables[vars] ] ]
-
- (* Multidimensional discrete-time Fourier transform *)
- multiDDTFT[ f1_, nl_, wl_, zl_, oplist_ ]:=
- Block [ {fun = f1, i, len, newop},
- len = Length[nl];
- newop = MultiDLookup[oplist, nl, wl];
- For [ i = 1, i <= len, i++,
- fun = MyDTFT[fun, nl[[i]], wl[[i]], zl[[i]], newop] ];
- fun ]
-
- (* One-dimensional discrete-time Fourier transform *)
- MyDTFT[ x_, n_, w_, z_, oplist_ ] :=
- Block [ {newexpr = myDTFT[x, n, w, z, fixUp[oplist], initDTFTstate[]],
- newdtftrules, newtrans, oldexpr = Null, ret, trace},
-
- (* generate the DTFT rules *)
- newdtftrules = TransformFixUp[ n, w, oplist, myDTFT, False,
- DTFTransform, Null, Null ];
- DTFTRules = Join[ newdtftrules, OriginalDTFTRules ];
-
- (* determine the level of dialogue *)
- trace = SameQ[ Replace[Dialogue, oplist], All ];
-
- (* take the 1-D DTFT *)
- Off[ Power::infy ];
- While [ ! SameQ[newexpr, oldexpr],
- If [ trace, Print[newexpr]; Print[ "which becomes" ] ];
- oldexpr = newexpr;
- newexpr = oldexpr /. ( myDTFT[a__] :>
- Replace[ myDTFT[a], DTFTRules ] ) ];
-
- (* fix up the result *)
- newexpr = posttransform[oldexpr];
- While [ ! SameQ[newexpr, oldexpr],
- If [ trace, Print[newexpr]; Print[ "which becomes" ] ];
- oldexpr = newexpr;
- newexpr = posttransform[oldexpr] ];
-
- (* convert any remaining z-transform artifacts *)
- If [ ! FreeQ[{newexpr}, z],
- newexpr = ( newexpr /. z -> Exp[I w] ) ];
- On[ Power::infy ];
- If [ trace, Print[newexpr] ];
- newtrans = If [ SameQ[Head[newexpr], ZTransData],
- TheFunction[newexpr],
- newexpr ];
-
- (* properly handle Periodic operators *)
- newtrans = newtrans /.
- Periodic[k_, e_][f_] :> Periodic[k, Expand[e]][f];
- newtrans = newtrans //.
- { a_ Periodic[k_, w][f_] :> Periodic[k, w][a f],
- Periodic[k_, w + w0_][f_] :> Periodic[k, w][f] /;
- FreeQ[w0, w], (* ignore shifts *)
- Periodic[k_, a_ w + w0_.][f_] :>
- Periodic[k / a, w][f] /;
- FreeQ[w0, w] }; (* scale axis *)
- If [ trace, Print[ "which becomes" ]; Print[newexpr] ];
-
- (* simplify expression if requested *)
- If [ Replace[Simplify, op],
- newtrans = SPSimplify[newtrans,
- Dialogue -> trace,
- Variables -> wList] ];
-
- newtrans ]
-
- (* Supporting Routines *)
-
- diagonalResamplingMatrixQ[mat_] := False /; ! MatrixQ[mat]
- diagonalResamplingMatrixQ[mat_] :=
- Block [ {cond = False, diag, dims, i},
- dims = Dimensions[mat];
- If [ dims[[1]] == dims[[2]],
- diag = Table[ mat[[i,i]], { i, 1, dims[[1]] } ];
- cond = Apply[And, Map[isinteger, diag] ] &&
- SameQ[mat, DiagonalMatrix[diag]] ];
- cond ]
-
- explain[ myDTFT[ x_, n_, rest__ ] ] :=
- Message[ Transform::incomplete,
- "forward discrete-time Fourier transform", x, n ]
-
- (* fixUp -- removes redundancy and TransformLookup in options list *)
- fixUp[ op_ ] := { Definition -> Replace[Definition, op],
- Dialogue -> Replace[Dialogue, op] }
-
- isinteger[x_] := Implies[ NumberQ[x], IntegerQ[x] ]
-
- isintegerMatrix[ x_ ] :=
- MatrixQ[x] && Apply[ SameQ, Dimensions[x] ] &&
- Apply[ And, Map[isinteger, Flatten[x]] ]
-
- mDresampleCheck[Downsample, n_, nvars_, nList_, m_] :=
- mDresampleCheck[Upsample, n, nvars, nList, m]
-
- mDresampleCheck[Upsample, n_, nvars_, nList_, l_] :=
- Block [ {cond},
- cond = SubsetQ[{n}, nvars, nList] && isintegerMatrix[l];
- If [ cond, Needs[ "SignalProcessing`Digital`MDDTFT`" ] ];
- cond ]
-
- posttransform[x_] := ( x /. postrules )
-
- postrules = {
- (* Apply the definition *)
- myDTFT[ x_, n_, w_, z_, options_, flag_ ] :>
- Block [ {def, summhead},
- summhead = If [ TrueQ[$VersionNumber >= 2.0],
- Needs[ "Algebra`SymbolicSum`" ];
- Algebra`SymbolicSum,
- Needs[ "Algebra`GosperSum`" ];
- Algebra`GosperSum ];
- def = summhead[x Exp[I w n], {n, -Infinity, Infinity}];
- TransformDialogue[ Definition, options,
- summhead, x, def ] ] /;
- Replace[Definition, options],
-
- derivative[x_, w_, 1] :>
- I D[ posttransform[x], w ],
- derivative[x_, w_, k_] :>
- I^k D[ posttransform[x], {w, k} ],
- downsample[x_, w_Symbol, m_Integer] :>
- Block [ {k, newx},
- newx = posttransform[x] /. w -> ((w + 2 Pi k) / m);
- Sum[newx, {k, 0, Abs[m]-1}] / Abs[m] ],
- downsample[x_, w_Symbol, m_] :>
- Block [ {k, newx},
- k = Unique["k"];
- newx = posttransform[x] /. w -> ((w + 2 Pi k) / m);
- Summation[k, 0, Abs[m]-1, 1][newx] / Abs[m] ],
- DTFTtoZ[x_] :>
- Transform[ x, 0, Infinity ],
- DTFTtoZ[x_, w_, z_] :>
- Transform[ substituteforw[x, w, -I Log[z]], 0, Infinity ],
- myDTFT[ZTransData[x_, zrest__], rest__] :>
- x,
- substituteforw[x_, w_Symbol, w0_, opstr_, op_] :>
- op[substituteforw[x, w, w - w0], substituteforw[x, w, w + w0]],
- substituteforw[x_, w_Symbol, -w] :>
- If [ Count[{x}, f_[p___][a___], Infinity] > 0,
- Rev[w][posttransform[x]], (* operators present *)
- posttransform[x] /. w -> -w ] , (* no operators *)
- substituteforw[x_, w_Symbol, wnew_] :>
- ( posttransform[x] /. w -> wnew ),
- upsamplemD[x_, {}, w_List, l_?MatrixQ] :>
- ( posttransform[x] /. ReplaceWith[w, l . w] ),
- upsamplemD[x_, nlist_, w_, l_] :>
- upsamplemD[ posttransform[x], nlist, w, l ],
- downsamplemD[x_, {}, w_, m_?MatrixQ] :>
- postdownsamplemD[x, w, m],
- downsamplemD[x_, nlist_, w_, m_] :>
- downsamplemD[ posttransform[x], nlist, w, m ]
- }
-
- ZtoDTFT[ SignalProcessing`Digital`ZTransform`Private`forwardz[x_, zrest__], n_, w_, z_, rest__ ] :=
- DTFTtoZ[ myDTFT[x, n, w, z, rest], w, z ]
- ZtoDTFT[ x_, n_, w_, z_, rest__ ] := x
-
-
- (* Printed forms of supported routines for Dialogue -> All option *)
-
- Format[ myDTFT[ x_, n_, w_, z_, options_, flag_ ] ] :=
- SequenceForm[ ColumnForm[{"DTFT",
- " " ~StringJoin~ ToString[n]}],
- { x } ]
-
- Format[ derivative[x_, w_Symbol, k_] ] :=
- SequenceForm[ ColumnForm[{"D" Superscript[k],
- " " ~StringJoin~ ToString[w]}],
- { x } ]
-
- Format[ substituteforw[x_, w_, wnew_] ] :=
- SequenceForm[ {x}, Subscript[w -> wnew] ]
-
- Format[ substituteforw[x_, w_, w0_, opstr_, op_] ] :=
- SequenceForm[ {x}, Subscript[w -> w - w0], opstr,
- {x}, Subscript[w -> w + w0] ]
-
- Format[ DTFTtoZ[x_, w_, z_] ] :=
- SequenceForm[ {x}, Subscript[w -> -I Log[z]] ]
-
- Format[ downsample[x_, w_, m_] ] :=
- SequenceForm[ {x}, Subscript[w -> ((w + 2 Pi "k")/m)] ]
-
- Format[ downsamplemD[x_, n_, w_, m_] ] :=
- SequenceForm[ {x}, Subscript["aliased by " m] ]
-
- Format[ upsamplemD[x_, n_, w_, m_] ] :=
- SequenceForm[ {x}, Subscript[w -> m . w] ]
-
-
- Format[ z ] := "z"
-
-
- (* S T A T E *)
-
- initDTFTstate[] := True
- nullDTFTstate[] := False
-
-
- (* B E G I N D T F T R U L E B A S E *)
-
-
- DTFTRules = {}
-
-
- OriginalDTFTRules = {
-
-
- (* A. Lookup rules *)
- (* 1. Pulse *)
- myDTFT[ Pulse[L_, n_ + n0_.], n_, w_, z_, options_, flag_ ] :>
- Periodic[2 Pi, w][Exp[I w n0] Exp[- I w (L - 1) / 2] Dirichlet[L, w]] /;
- FreeQ[{L, n0}, n],
-
- myDTFT[ A_. Step[n_ + n0_.] - A_. Step[n_ + n1_.] + x_, n_, w_, z_, options_, flag_ ] :>
- myDTFT[ A Pulse[Abs[n1 - n0], n + Min[-n0, -n1]],
- n, w, z, options, flag ] +
- myDTFT[ x, n, w, z, options, flag ] /;
- FreeQ[{n0, n1}, n],
-
- (* 2. Step *)
- myDTFT[ Step[n_ + n0_.], n_, w_, z_, options_, flag_ ] :>
- Block [ {l = unique["l"]},
- Exp[I w n0] / ( 1 - Exp[-I w] ) +
- Pi Exp[I w n0] Summation[l, -Infinity, Infinity, 1]
- [Delta[w + 2 Pi l]] ] /;
- FreeQ[n0, n],
-
- (* 3. Summation forms *)
- myDTFT[ Summation[k_, -Infinity, Infinity, 1][x_],
- n_, w_, z_, options_, flag_ ] :>
- Summation[k,-Infinity,Infinity,1][
- myDTFT[x, n, w, z, options, flag] ] /;
- FreeQ[k, n],
-
- myDTFT[ Summation[k_, 0, L_, 1][a_. Exp[I m_ Pi k_ n_]],
- n_, w_, z_, options_, flag_ ] :>
- 2 Pi Summation[k, -Infinity, Infinity,1][a Delta[w - 2 Pi k/(L+1)]] /;
- FreeQ[{a, k, L}, n] && SameQ[m, 2/(L+1)],
-
- (* 4. Infinite extent cosine *)
- myDTFT[ Cos[w0_. n_ + b_.], n_, w_, z_, options_, flag_ ] :>
- Block [ {l = unique["l"]},
- Pi Summation[l,-Infinity,Infinity,1]
- [Exp[I b w / w0] Delta[w - w0 + 2 Pi l] +
- Exp[- I b w / w0] Delta[w + w0 + 2 Pi l]] ] /;
- FreeQ[{b, w0}, n],
-
- (* 5. Infinite extent sine *)
- myDTFT[ Sin[w0_. n_ + b_.], n_, w_, z_, options_, flag_ ] :>
- Block [ {l = unique["l"]},
- Pi Summation[l,-Infinity,Infinity,1]
- [- I Exp[I b w / w0] Delta[w - w0 + 2 Pi l] +
- I Exp[I b w / w0] Delta[w + w0 + 2 Pi l]] ] /;
- FreeQ[{b, w0}, n],
-
- (* 6. Constant function *)
- myDTFT[ 1, n_, w_, z_, options_, flag_ ] :>
- Block [ {l = unique["l"]},
- 2 Pi Summation[l,-Infinity,Infinity,1][Delta[w + 2 Pi l]] ],
-
- (* 7. Sinc and other 1/n *)
- myDTFT[ (-1)^(n_ + a_.) / ( n_ - 1 ), n_, w_, z_, options_, flag_ ] :>
- Periodic[2 Pi, w][ (-1)^a w Exp[- I w] CPulse[2 Pi, w + Pi] ] /;
- FreeQ[a, n],
-
- myDTFT[ 1/n_, n_, w_, z_, options_, flag_ ] :>
- Periodic[2 Pi, w][ - 2 Pi I CStep[w] ],
-
- myDTFT[ Sinc[a_. n_ + b_.], n_, w_, z_, options_, flag_ ] :>
- Periodic[2 Pi, w][ Exp[I b/a] Pi CPulse[2 Abs[a], w + Abs[a]] /
- Abs[a] ] /;
- FreeQ[{a,b}, n],
-
- myDTFT[ (Sinc[a_. n_ + b_.])^2, n_, w_, z_, options_, flag_ ] :>
- Periodic[2 Pi, w][ Exp[I b / a] (Pi / a)^2 ( Unit[-2][w + 2 a] -
- 2 Unit[-2][w] + Unit[-2][w - 2 a] ) ] /;
- FreeQ[{a,b}, n],
-
-
- (* B. Properties *)
- (* 1. Multiplication by constant *)
- myDTFT[ a_ x_, n_, w_, z_, options_, flag_ ] :>
- a myDTFT[x, n, w, z, options, flag] /;
- FreeQ[a, n],
-
- (* 2. Additivity property *)
- myDTFT[ x_ + y_, n_, w_, z_, options_, flag_ ] :>
- myDTFT[x, n, w, z, options, flag] + myDTFT[y, n, w, z, options, flag],
-
- (* 3. Multiplication by n *)
- myDTFT[ n_^a_. b_, n_, w_, z_, options_, flag_ ] :>
- Block [ {dialogue},
- dialogue = SameQ[ Replace[Dialogue, options], All ];
- Assuming[ a > 0, dialogue ];
- If [ dialogue, Print[ "where ", a, " is an integer" ] ];
- derivative[myDTFT[b, n, w, z, options, flag], w, a] ] /;
- FreeQ[a,n] && Implies[ NumberQ[a], IntegerQ[a] && a > 0 ],
-
- (* 4. Delay by m *)
- myDTFT[ f_. Step[n_ + m_], n_, w_, z_, options_, flag_ ] :>
- Exp[I m w] myDTFT[(f /. n->(n - m)) Step[n], n, w, z, options, flag] /;
- FreeQ[m, n],
-
- (* 5. Expand shifted sinusoids *)
- myDTFT[ Cos[a_. n_ + b_] x_., n_, w_, z_, options_, flag_ ] :>
- myDTFT[ Cos[b] Cos[a n] x - Sin[b] Sin[a n] x,
- n, w, z, options, flag ] /;
- FreeQ[{a, b}, n],
-
- myDTFT[ Sin[a_. n_ + b_] x_., n_, w_, z_, options_, flag_ ] :>
- myDTFT[ Sin[b] Cos[a n] x + Cos[b] Sin[a n] x,
- n, w, z, options, flag ] /;
- FreeQ[{a, b}, n],
-
- (* 6. Multiplication by complex exponential *)
- myDTFT[ a_. Exp[Complex[0, w0_] w1_. n_ + b_.], n_, w_, z_, options_, flag_ ] :>
- Exp[b] substituteforw[ myDTFT[a, n, w, z, options, flag],
- w, w - w0 w1 ] /;
- FreeQ[{b, w0, w1}, n],
-
- myDTFT[ a_. Cos[w0_. n_], n_, w_, z_, options_, flag_ ] :>
- substituteforw[ myDTFT[a, n, w, z, options, flag] / 2,
- w, w0, "+", Plus ] /;
- FreeQ[w0, n],
-
- myDTFT[ a_. Sin[w0_. n_], n_, w_, z_, options_, flag_ ] :>
- substituteforw[ -I/2 myDTFT[a, n, w, z, options, flag],
- w, w1, "-", Subtract ] /;
- FreeQ[w0, n],
-
- (* C. Structures *)
- (* -. An operator independent of n--- take transform of f *)
- myDTFT[ operator_[params__][f_], n_, w_, z_, options_, flag_ ] :>
- operator[params][ myDTFT[f, n, w, z, options, flag] ] /;
- FreeQ[{params}, n],
-
- (* 1. Upsampling *)
- myDTFT[ Upsample[l_, n_] [ x_ ], n_, w_, z_, options_, flag_ ] :>
- substituteforw[ myDTFT[x, n, w, z, options, flag], w, l w],
-
- myDTFT[ Upsample[l_, nvars_List] [ x_ ], n_, w_, z_, options_, flag_ ] :>
- Block [ {dim, expr, i},
- dim = Length[nvars];
- expr = x;
- For [ i = 1, i <= dim, i++,
- expr = Upsample[ l[[i,i]], nvars[[i]] ][expr] ];
- myDTFT[ expr, n, w, z, options, flag ] ] /;
- MemberQ[nvars, n] && diagonalResamplingMatrixQ[l],
-
- myDTFT[ Upsample[l_, nvars_List] [ x_ ], n_, w_, z_, options_, flag_ ] :>
- upsampleSetUp[l, nvars, x, n, w, z, options, flag ] /;
- mDresampleCheck[Upsample, n, nvars, nList, l],
-
- myDTFT[ upsamplemD[ x_, nlist_, wlist_, l_], n_, w_, z_, options_, flag_ ] :>
- upsamplemD[ myDTFT[x, n, w, z, options, flag ],
- If [ MemberQ[nlist, n], Complement[nlist, {n}], nlist ],
- wlist, l ],
-
- (* 2. Downsampling *)
- myDTFT[ Downsample[m_, n_] [ x_ ], n_, w_, z_, options_, flag_ ] :>
- downsample[ myDTFT[x, n, w, z, options, flag], w, m ],
-
- myDTFT[ Downsample[m_, nvars_List] [ x_ ], n_, w_, z_, options_, flag_ ] :>
- Block [ {dim, expr, i},
- dim = Length[nvars];
- expr = x;
- For [ i = 1, i <= dim, i++,
- expr = Downsample[ m[[i,i]], nvars[[i]] ][expr] ];
- myDTFT[expr, n, w, z, options, flag] ] /;
- MemberQ[nvars, n] && diagonalResamplingMatrixQ[m],
-
- myDTFT[ Downsample[m_, nvars_List] [ x_ ], n_, w_, z_, options_, flag_ ] :>
- downsampleSetUp[m, nvars, x, n, w, z, options, flag ] /;
- mDresampleCheck[Downsample, n, nvars, nList, m],
-
- myDTFT[ downsamplemD[ x_, nlist_, wlist_, m_], n_, w_, z_, options_, flag_ ] :>
- downsamplemD[ myDTFT[x, n, w, z, options, flag ],
- If [ MemberQ[nlist, n], Complement[nlist, {n}], nlist ],
- wlist, m ],
-
- (* D. Strategies *)
- (* 1. Multiply out terms in cosine, sin, and exponential functions. *)
- myDTFT[ Exp[a_] x_., n_, w_, z_, options_, flag_ ] :>
- myDTFT[ Exp[Expand[a]] x, n, w, options, flag ] /;
- ! SameQ[Exp[a], Exp[Expand[a]]],
-
- myDTFT[ Cos[a_] x_., n_, w_, z_, options_, flag_ ] :>
- myDTFT[ Cos[Expand[a]] x, n, w, options, flag ] /;
- ! SameQ[Cos[a], Cos[Expand[a]]],
-
- myDTFT[ Sin[a_] x_., n_, w_, z_, options_, flag_ ] :>
- myDTFT[ Sin[Expand[a]] x, n, w, options, flag ] /;
- ! SameQ[Sin[a], Sin[Expand[a]]],
-
- (* 2. Expand out products like (n + 1)(n + 2) ... *)
- myDTFT[ x_, n_, w_, z_, options_, flag_ ] :>
- myDTFT[ Distribute[x], n, w, z, options, flag ] /;
- SameQ[Head[x], Times] && ! SameQ[x, Distribute[x]],
-
- (* 3. Use the z-transform *)
- myDTFT[ x_, n_, w_, z_, options_, True ] :>
- Block [ {myz, nullstate, ztrans},
- nullstate = nullDTFTstate[];
- myz = SignalProcessing`Digital`ZTransform`Private`MyZByPass;
- ztrans = myz[ x, n, z, nList, zList,
- {Dialogue -> False} ~Join~ options ];
- If [ InformUserQ[options],
- Print[ "( after taking the z-transform of" ];
- Print[ " ", x ];
- Print[ " which yields" ];
- Print[ " ", ztrans ];
- Print[ " and adjusting the result )" ] ];
- If [ SameQ[Head[ztrans], ZTransData],
- ( TheFunction[ztrans] /. z -> Exp[I w] ),
- myDTFT[ MapAll[ ZtoDTFT[#1, n, w, z, options, nullstate]&,
- ztrans ],
- n, w, z, options, nullstate ] ] ]
-
- }
-
- (* E N D R U L E B A S E *)
-
- (* E N D F O R W A R D D T F T *)
-
-
- (* B E G I N I N V E R S E D T F T *)
-
- InvDTFTransform::noncont =
- "Discrete operators and functions were converted into continuous ones."
-
- (* Conversion from operator notation to function notation *)
- Unprotect[InvDTFT]
- InvDTFT/: TheFunction [ InvDTFT[w_, n_][f_] ] := InvDTFTransform[f, w, n]
- Protect[InvDTFT]
-
- (* Give it options *)
- InvDTFTransform/: Options[InvDTFTransform] :=
- displayFixUp[ invFixUp,
- Join[ { Definition -> False,
- Dialogue -> False,
- Terms -> False },
- Options[InvZTransform] ] ]
-
- (* Input a function and test to see if needs to be sent to the *)
- (* multidimensional or one-dimensional inverse Fourier transform. *)
- InvDTFTransform[ DTFTData[ trans_, FVariables[vars_] ] ] :=
- InvDTFTransform [ trans, vars ]
-
- InvDTFTransform[ f_ ] :=
- Message[ Transform::novariables, "w (frequency)", GetVariables[f] ]
-
- InvDTFTransform[ f_, w_ ] :=
- InvDTFTransform[ f, w, DummyVariables[Length[w], Global`n] ]
-
- InvDTFTransform[ f_, w_, n_, options___ ] :=
- Message[ Transform::badvar, "continuous-frequency",
- InvDTFTransform, w ] /;
- ! validvarQ[w]
-
- InvDTFTransform[ f_, w_, n_, options___ ] :=
- Message[ Transform::badvar, "discrete-time", InvDTFTransform, n ] /;
- ! validvarQ[n]
-
- InvDTFTransform[ f_, varin_, varout_, options___ ] :=
- Block [ {freqfun, invfun, op, vars, z, zvars},
- vars = If [ Length[varin] != Length[varout],
- DummyVariables[Length[varin], Global`n],
- varout ];
-
- zvars = DummyVariables[Length[varin], z];
-
- freqfun = ToContinuous[f];
- If [ ! SameQ[freqfun, f],
- Message[InvDTFTransform::noncont] ];
-
- wList = ToList[varin];
- nList = ToList[vars];
- zList = ToList[zvars];
-
- op = ToList[options] ~Join~ Options[InvDTFTransform];
- multidFlag = ( Length[varin] > 1 );
- invfun = If [ multidFlag,
- multiDInvDTFT[freqfun, varin, vars, zvars, op],
- MyInvDTFT[freqfun, varin, vars, zvars, op] ];
-
- If [ InformUserQ[op],
- Scan[invexplain, invfun, Infinity] ];
-
- invfun ]
-
- (* Multidimensional inverse discrete-time Fourier transform *)
- multiDInvDTFT[ f_, wl_, nl_, zl_, oplist_ ] :=
- Block [ {fun = f, i, len, newop},
- len = Length[wl];
- newop = MultiDLookup[oplist, wl, nl];
- For [ i = 1, i <= len, i++,
- fun = MyInvDTFT[fun, wl[[i]], nl[[i]], zl[[i]], newop] ];
- fun ]
-
- (* One-dimensional inverse discrete-time Fourier transform *)
- MyInvDTFT[ f_, w_, n_, z_, op_ ] :=
- Block [ {newexpr = myinvDTFT[f, w, n, z, invFixUp[op], {True, True}],
- newinvdtftrules, oldexpr = Null, trace},
-
- (* generate the inverse DTFT rules *)
- newinvdtftrules = TransformFixUp[ w, n, op, myinvDTFT, False,
- InvDTFTransform, Null, Null ];
- InvDTFTRules = Join[ newinvdtftrules, OriginalInvDTFTRules ];
-
- (* determine the level of dialogue *)
- trace = SameQ[ Replace[Dialogue, op], All ];
-
- (* take the 1-D inverse DTFT *)
- While [ ! SameQ[newexpr, oldexpr],
- If [ trace, Print[newexpr]; Print[ "which becomes" ] ];
- oldexpr = newexpr;
- newexpr = oldexpr /. ( myinvDTFT[a__] :>
- Replace[ myinvDTFT[a], InvDTFTRules ] ) ];
- If [ trace, Print[newexpr] ];
-
- (* fix up the result *)
- newexpr = postinvtransform[oldexpr];
- While [ ! SameQ[newexpr, oldexpr],
- If [ trace, Print[newexpr]; Print[ "which becomes" ] ];
- oldexpr = newexpr;
- newexpr = postinvtransform[oldexpr] ];
-
- (* simplify expression if requested *)
- If [ Replace[Simplify, op],
- newexpr = SPSimplify[newexpr,
- Dialogue -> trace,
- Variables -> nList] ];
-
- newexpr ]
-
-
- (* Supporting Routines *)
-
- breakItUp[ a_. f_, w_, k_ ] := { a, f } /;
- FreeQ[a, k] && ! FreeQ[f, k]
-
- checkFactoring[ a_, w_, k_ ] := breakItUp[ Factor[a], w, k ]
-
- checkFactoringQ[ a_, w_, k_ ] :=
- ! SameQ[ First[ checkFactoring[ a, w, k ] ], 1 ]
-
- candidateList = {}
- periodicX = {}
- nonPeriodicX = {}
-
- downShiftPair[x_, y_, m_] :=
- Block [ {diff, ratio},
- diff = x - y;
- If [ Apply[SameQ, diff],
- ratio = First[diff] / (2 Pi);
- IntegerQ[ratio] && ( -m <= ratio <= m ) ] ] /;
- Length[x] == Length[y]
-
- downsampled1DcheckQ[ x_Plus, w_, m_ ] :=
- Block [ {i, j, length, lengthList, newx, rule},
- newx = MyCollectAll[x, w];
- periodicX = {};
- rule = a_. Periodic[2 Pi m, w][f_] :>
- Block [ {}, AppendTo[periodicX, a f]; 0 ];
- nonPeriodicX = Map[ Replace[#, rule]&, newx ];
-
- (* Determine which functions are shifted versions of *)
- (* one another--- first compute all shift factors for *)
- (* each candidate and then compare them pairwise *)
- shiftFactors =
- Expand[ Map[ GetAllShiftFactors[#, w]&, periodicX ] ];
- length = Length[ shiftFactors ];
- lengthList = Map[ Length, shiftFactors ];
- For [ i = 1, i <= length, i++,
- candidateList = {i};
- For [ j = 1, j <= length, j++,
- If [ (i != j) &&
- downShiftPair[ shiftFactors[[i]],
- shiftFactors[[j]], m ],
- AppendTo[candidateList, j] ] ];
- If [ SameQ[Length[candidateList], m], Break[] ] ];
- SameQ[ Length[candidateList], m ] ]
-
- invexplain[ myinvDTFT[ x_, w_, rest__ ] ] :=
- Message[ Transform::incomplete,
- "inverse discrete-time Fourier transform", x, w ]
-
- (* invFixUp -- removes redundancy and TransformLookup in options list *)
- invFixUp[ op_ ] := { Definition -> Replace[Definition, op],
- Dialogue -> Replace[Dialogue, op],
- Terms -> Replace[Terms, op] }
-
- (* invertDownsampledDTFT *)
- invertDownsampledDTFT[ x_, w_, n_, z_, options_, flag_, m_ ] :=
- Block [ {},
- If [ ! IntegerQ[m],
- If [ SameQ[ Replace[Dialogue, options], All ],
- Print[ "assuming ", m, " is an integer" ] ] ];
- Abs[m] Downsample[m, n][
- myinvDTFT[x /. w -> m w, w, n, z, options, flag] ] ] /;
- Implies[ NumberQ[m], IntegerQ[m] ]
-
- (* invertResampledDTFT *)
- invertResampledDTFT[ x_, w_, n_, z_, options_, flag_, y_, f_ ] :=
- invertResampledDTFT[ x, w, n, z, options, flag,
- y, Numerator[f], Denominator[f] ]
-
- invertResampledDTFT[ x_, w_, n_, z_, options_, flag_, y_, m_, l_ ] :=
- Block [ {extraterms = 0, newx, upfact},
- upfact = If [ SameQ[m, 2], l, 2 l ];
- If [ IntegerQ[upfact] && upfact < 0, upfact = -upfact ];
- If [ ! IntegerQ[upfact],
- If [ SameQ[ Replace[Dialogue, options], All ],
- Print[ "assuming ", upfact, " is an integer" ] ] ];
- newx = x /. w -> (w/upfact);
- If [ SameQ[y, 0],
- extraterms = myinvDTFT[y, w, n, z, options, flag] ];
- extraterms +
- Upsample[upfact, n][
- myinvDTFT[newx, w, n, z, options, flag] ] ] /;
- ( SameQ[m, 2] || SameQ[m, 1] ) && FreeQ[l, w] && (! SameQ[l, 1]) &&
- Implies[ NumberQ[l], IntegerQ[l] ]
-
- invertResampledDTFT[ x_, w_, n_, z_, options_, flag_, y_, m_Integer, 1 ] :=
- Block [ {extraterms},
- extraterms = nonPeriodicX;
- If [ Length[candidateList] < m/2,
- indices = Intersection[ Range[m/2], candidateList ];
- extraterms += Apply[ Plus, periodicX[[indices]] ] ];
- thefun = periodicX[[ First[candidateList] ]];
- If [ ! SameQ[extraterms, 0],
- extraterms =
- myinvDTFT[extraterms, w, n, z, options, flag] ];
- invertDownsampledDTFT[ thefun, w, n, z, options, flag, m/2 ] +
- extraterms ] /;
- EvenQ[m] && ( m > 2 ) &&
- downsampled1DcheckQ[ Periodic[m Pi, w][x] + y, w, m/2 ]
-
- invertResampledDTFT[ x_, w_, n_, z_, options_, flag_, y_, m_Integer, 1 ] :=
- invertResampledDTFT[x, w, n, z, options, flag, y, 2 m, 2 ] /;
- OddQ[m]
-
-
- postinvtransform[x_] := ReplaceRepeated[x, postinvrules]
-
- postinvrules = {
-
- (* 4. Apply the definition *)
- myinvDTFT[ a_ Pulse[l_, w_ + s_.], w_, n_, z_, options_, flag_ ] :>
- TransformDialogue[ Definition, options, Integrate,
- a Pulse[l, w + s],
- Integrate[ a Exp[I w n], {w, -s, l - s}] / (2 Pi) ] /;
- Replace[Definition, options] && N[(Pi > s) && (Pi < l - s)],
-
- myinvDTFT[ x_, w_, n_, z_, options_, flag_ ] :>
- TransformDialogue[ Definition, options, Integrate, x,
- Integrate[x Exp[I w n], {w, -Pi, Pi}] / (2 Pi) ] /;
- Replace[Definition, options],
-
- substituteforn[x_, n_Symbol, -n_] :>
- If [ Count[{x}, f_[p___][a___], Infinity] > 0,
- Rev[n][posttransform[x]], (* operators present *)
- posttransform[x] /. n -> -n ] , (* no operators *)
-
- substituteforn[x_, n_, newn_] :> ( x /. n -> newn )
- }
-
- (* Routines to detect upsampling in the frequency response *)
-
- upsamplefactorQ[ f_ ] := (! SameQ[f, 0]) && (! SameQ[f, 1]) && (! SameQ[f, -1])
- upsampledQ[ x_, w_ ] := upsamplefactorQ[ UpsampleFactor[x, w, GetAllFactors] ]
-
- upsampledmDQ[ x_, w_ ] :=
- Block [ {cond},
- cond = ! MyFreeQ[ GetAllShiftFactors[x, w], wList ];
- If [ cond,
- Needs[ "SignalProcessing`Digital`MDDTFT`" ];
- cond = upsampleSystemQ[ x, wList ] ];
- cond ]
-
-
- (* Printed forms of supported routines for Dialogue -> All option *)
-
- Format[ myinvDTFT[ x_, w_, n_, z_, options_, flag_ ] ] :=
- SequenceForm[ ColumnForm[{"DTFT" Superscript[-1],
- " " ~StringJoin~ ToString[w]}],
- { x } ]
-
- Format[ substituteforn[x_, n_, newn_] ] :=
- SequenceForm[ {x}, Subscript[n -> newn] ]
-
-
- (* B E G I N R U L E B A S E *)
-
-
- InvDTFTRules = {}
-
-
- OriginalInvDTFTRules = {
-
-
- myinvDTFT[ Periodic[2 Pi, w_][x_], w_, n_, z_, options_, flag_ ] :>
- myinvDTFT[x, w, n, z, options, flag],
-
-
- (* A. Lookup Rules *)
- (* 1. Summation forms *)
- myinvDTFT[ Summation[k_,-Infinity,Infinity,1][a_. Delta[w_+w0_.+b_. Pi k_] +
- a_. Delta[w_ + A_. + c_. Pi k_] + x_.],
- w_, n_, z_, options_, flag_ ] :>
- a Cos[A n] / Pi + Summation[k, -Infinity, Infinity, 1][x] /;
- ( A == - w0 ) && ( SameQ[b, 2] || SameQ[b, -2] ) &&
- ( SameQ[c, 2] || SameQ[c, -2] ) && FreeQ[{a, k, w0}, w],
-
- myinvDTFT[ Summation[k_,-Infinity,Infinity,1][a_. Delta[w_+w0_.+b_. Pi k_] +
- d_. Delta[w_+A_.+c_. Pi k_] + x_.],
- w_, n_, z_, options_, flag_ ] :>
- (a I) Sin[A n] / Pi + Summation[k, -Infinity, Infinity, 1][x] /;
- ( A == -w0 ) && ( a == -d ) && ( SameQ[b, 2] || SameQ[b, -2] ) &&
- ( SameQ[c, 2] || SameQ[c, -2] ) && FreeQ[{a, A, w0}, w],
-
- myinvDTFT[ Summation[k_, -Infinity, Infinity, 1][
- a_. Delta[w_+w0_.+b_. Pi k_] + x_.],
- w_, n_, z_, options_, flag_ ] :>
- a Exp[- I w0 n] / (2 Pi) + Summation[k, -Infinity, Infinity, 1][x] /;
- ( SameQ[b, 2] || SameQ[b, -2] ) && FreeQ[{a, k, w0}, w],
-
- myinvDTFT[ Summation[k_,-Infinity,Infinity,1][a_. Delta[w_ + b_. Pi k_ / L_]],
- w_, n_, z_, options_, flag_ ] :>
- L/(2 Pi) Summation[k,-Infinity,Infinity,1][a Exp[I 2 Pi k n / (L+1)]] /;
- FreeQ[{a, k, L}, w] && ( SameQ[b, -2] || SameQ[b, 2] ),
-
- (* 2. Constant function *)
- myinvDTFT[ a_, w_, n_, z_, options_, flag_ ] :> a Impulse[n] /; FreeQ[a, w],
-
- (* 3. Pulse in continuous frequency *)
- myinvDTFT[ CPulse[L_, a_. w_ + w1_.], w_, n_, z_, options_, flag_ ] :>
- L/a Exp[I w1 n / a] Exp[- I L n / (2 a)] Sinc[L n / (2 a)] / (2 Pi) /;
- FreeQ[{a, L, w1}, w],
-
- myinvDTFT[ A_. CStep[w_ + w0_.] - A_. CStep[w_ + w1_.] + x_.,
- w_, n_, z_, options_, flag_ ] :>
- myinvDTFT[ A CPulse[w0 - w1, w + w0], w, n, z, options, flag ] +
- myinvDTFT[ x, w, n, z, options, flag ] /;
- FreeQ[{w0, w1}, w],
-
- (* 4. Step function *)
- myinvDTFT[ 1 / ( 1 - Exp[- I w_] ) +
- p1_. Summation[k_,-Infinity,Infinity,1][p2_. Delta[w_ + b_. Pi k_]],
- w_, n_, z_, options_, flag_] :>
- Step[n] /;
- FreeQ[k, w] && SameQ[p1 p2, Pi] && ( SameQ[b, 2] || SameQ[b, -2] ),
-
- (* 5. Dirichlet kernel (aliased sinc) *)
- myinvDTFT[ Dirichlet[L_, w_ + w0_.], w_, n_, z_, options_, flag_ ] :>
- Exp[- I w0 n] Pulse[L, n + (L - 1)/2] /;
- FreeQ[{L, w0}, w],
-
- (* 6. Differentiator (high pass) filter *)
- myinvDTFT[ w_ CPulse[2 Pi, w_ + Pi], w_, n_, z_, options_, flag_ ] :>
- -2 I Pi (-1)^n / n,
-
-
- (* B. Properties *)
- (* 1. Resampling--- all Periodic[2 Pi, w] operators have already *)
- (* been processed by the rule base. *)
- myinvDTFT[ Summation[k_, 0, Lminus1_, 1][ Periodic[m_. Pi, w_][ x_ ] ],
- w_, n_, z_, options_, flag_ ] :>
- invertDownsampledDTFT[ x /. k -> 0, w, n, z, options, flag, m/2 ] /;
- ( SameQ[m/2, Lminus1 + 1] || SameQ[Abs[m/2], Lminus1 + 1] ) &&
- ( Count[ x, w/(m/2) + 2 Pi k/(m/2) + h_., Infinity ] > 0 ||
- Count[ x, (w + 2 Pi k + h_.)/(m/2), Infinity ] > 0 ),
-
- myinvDTFT[ Periodic[m_. Pi, w_][ x_ ] + y_., w_, n_, z_, options_, flag_ ] :>
- invertResampledDTFT[ x, w, n, z, options, flag, y, Rationalize[m] ],
-
- (* 2. Multiplication by a constant *)
- myinvDTFT[ a_ x_, w_, n_, z_, options_, flag_ ] :>
- a myinvDTFT[x, w, n, z, options, flag] /;
- FreeQ[a, w],
-
- (* 3. Additivity *)
- myinvDTFT[ a_ + b_, w_, n_, z_, options_, flag_ ] :>
- myinvDTFT[a, w, n, z, options, flag] +
- myinvDTFT[b, w, n, z, options, flag],
-
- (* 4. Multiplication by a complex exp. *)
- myinvDTFT[ Exp[Complex[0, n1_] n0_. w_ + b_.] x_.,
- w_, n_, z_, options_, flag_ ] :>
- Exp[b] substituteforn[ myinvDTFT[x, w, n, z, options, flag],
- n, n + n0 n1 ] /;
- FreeQ[{b, n0, n1}, w],
-
- (* 4. Summation *)
- myinvDTFT[ x_. / ( 1 - Exp[- I w_] ) +
- Pi Summation[k_,-Infinity,Infinity,1][Delta[w_ + b_. Pi k_]],
- w_, n_, z_, options_, flag_ ] :>
- Summation[k, -Infinity, Infinity, 1][
- myinvDTFT[x, w, n, z, options, flag] ] /;
- FreeQ[k, w] && ( SameQ[b, -2] || SameQ[b, 2] ),
-
- myinvDTFT[ b_. Summation[k_,-Infinity,Infinity,1][a_],
- w_, n_, z_, options_, flag_ ] :>
- Block [ {f, newdtft, rest},
- {f, rest} = checkFactoring[a, w, k];
- newdtft = b f Summation[k,-Infinity,Infinity,1][Expand[rest]];
- myinvDTFT[ newdtft, w, n, z, options, flag ] ] /;
- checkFactoringQ[a, w, k],
-
- (* 5. Multdimensional upsampling *)
- myinvDTFT[ x_, w_, n_, z_, options_, flag_ ] :>
- undoUpsampling[ x, w, n, z, options, flag ] /;
- multidFlag && upsampledmDQ[ x, w ],
-
- (* 6. An operator independent of w--- take transform of f *)
- myinvDTFT[ operator_[params__][f_], w_, n_, z_, options_, flag_ ] :>
- operator[params][ myinvDTFT[f, w, n, z, options, flag] ] /;
- FreeQ[{params}, w],
-
-
- (* C. Strategies *)
- (* 1. Collect all subexpressions in terms of w *)
- myinvDTFT[ x_, w_, n_, z_, options_, {True, flag2_} ] :>
- myinvDTFT[ MyCollectAll[x, w], w, n, z, options, { False, flag2 } ],
-
- (* 2. Expand out products like (w + 1)(w + 2) ... *)
- myinvDTFT[ x_, w_, n_, z_, options_, flag_ ] :>
- myDTFT[ Distribute[x], n, w, z, options, flag ] /;
- SameQ[Head[x], Times] && ! SameQ[x, Distribute[x]],
-
- (* 3. Take inverse z-transform *)
- myinvDTFT[ x_, w_, n_, z_, options_, {flag1_, True} ] :>
- Block [ {myinvz, newx, invztrans},
- newx = SPSimplify[ ( x /. w -> ( - I Log[z] ) ) ];
- myinvz =
- SignalProcessing`Digital`InvZTransform`Private`MyInvZByPass;
- invztrans = myinvz[ newx, z, n, zList, nList,
- {Dialogue -> False} ~Join~ options ];
- If [ InformUserQ[options],
- Print[ "( after taking the inverse z-transform of" ];
- Print[ " ", x ];
- Print[ " which yields" ];
- Print[ " ", invztrans ];
- Print[ " and adjusting the result )" ] ];
- If [ InvalidInvZTransformQ[invztrans],
- myinvDTFT[ invztrans, w, n, z, options, {flag1, False} ],
- invztrans ] ],
-
- (* Clean up expression returned from inverse z-transform *)
- myinvDTFT[SignalProcessing`Digital`InvZTransform`Private`myinvz[x_, z_, rest__], w_, n_, z_, options_, flag_ ] :>
- Block [ {dtftform},
- dtftform = SPSimplify[ ( x /. z -> Exp[I w] ) ];
- myinvDTFT[dtftform, w, n, z, options, flag] ]
-
- }
-
-
- (* E N D R U L E B A S E *)
-
- (* E N D I N V E R S E D T F T *)
-
-
- (* E N D P A C K A G E *)
-
- End[]
- EndPackage[]
-
- If [ TrueQ[ $VersionNumber >= 2.0 ],
- On[ General::spell ];
- On[ General::spell1 ] ];
-
-
- (* H E L P I N F O R M A T I O N *)
-
- Combine [ SPfunctions, { DTFTransform, InvDTFTransform } ]
- Protect [ DTFTransform, InvDTFTransform ]
-
-
- (* E N D I N G M E S S A G E *)
-
- Print["The discrete-time Fourier transform (DTFT) rule bases are loaded."]
- Null
-